(function($){
String.format = function()
				{
					var currentString = null;
					if (arguments.length != 0)
					{
						currentString = arguments[0];
						for (var argumentIndex = 1; argumentIndex < arguments.length; argumentIndex++)
						{
							var modifiedString = new RegExp('\\{' + (argumentIndex - 1) + '\\}','gm');
							currentString = currentString.replace(modifiedString, arguments[argumentIndex]);
						}
					}
					
					return currentString;
				};
var iExpandableSelect =function(options,elem) {
   
    this.optionClicked = false;
	this.scrollClicked = false;
    this.settings = options;
  	this.init = function(elem)
	{
	  var options = this.settings;
	  var container = "<div class=\'"+ options.containerClass +"\' style =\'" + $(elem).attr('style')+"\'>";
	 	  var selectedOptionElement = $(elem).children(':first');
	  // As of now all the select box need to reset to default hence resetting .
	  /*  if($(elem).val()=="")
	  {
	    selectedOptionElement=$(elem).children(':first');
	  }
	  else{
	    selectedOptionElement=$(elem).children().filter(function(){
		return $(this).val()==$(elem).val()}); 
		}
       */
	  var selectedOption = String.format("<div tabindex=0 class=\'{0} {1}\'><div><span rel=\'{2}\' class=\'{3}\' style=\'{4}\'>{5}</span></div></div>",options.optionsSelectedStyle,$(elem).attr('class'),$(elem).val(),$(selectedOptionElement).attr('class'),$(selectedOptionElement).attr('style'),$(selectedOptionElement).text());            
 	  var displayElement = container + selectedOption+"<ul style=\"display:none\" >";
      var listoptions =  $(elem).children('option');
	  var listItem = displayElement;
      listoptions.each(function(){
	         //if($(this).val()==$(elem).val())
			  if($(this).val()== selectedOptionElement.val())
             listItem = listItem  + String.format("<li  rel=\'{0}\' class=\'{1} {2}\'  style=\'{3}\'>{4}</li>",$(this).val(),'highlight',$(this).attr('class'),$(this).attr('style'),$(this).text()); 
			 else listItem = listItem  + String.format("<li  rel=\'{0}\' class=\'{1}\'  style=\'{2}\'>{3}</li>",$(this).val(),$(this).attr('class'),$(this).attr('style'),$(this).text());
	   });
	   displayElement = listItem + "</ul></div>";
	  $(elem).hide();
      $(elem).after(displayElement);
      $(elem).bind('enabled',this,function(event){
           event.data.enable(this);
    	  });
      $(elem).bind('disabled',this,function(event){
           event.data.disable(this);
    	  });
	  if($(elem).attr('disabled'))
       {
	   $(elem).next().find('.'+ options.optionsSelectedStyle).addClass('disabled');
 	   return;
	   }
      $(elem).next().css('zIndex',1);
      this.bindHandlers(elem); 
	  this.keyHandlers(elem); 
 	};	

    this.enable = function(elem){
      if($(elem).next().find('.'+ options.optionsSelectedStyle).hasClass('disabled')) $(elem).next().find('.'+ options.optionsSelectedStyle).removeClass('disabled');
      this.bindHandlers(elem); 
	  this.keyHandlers(elem); 
	};

    this.disable = function(elem){
       if(!$(elem).next().find('.'+ options.optionsSelectedStyle).hasClass('disabled')) $(elem).next().find('.'+ options.optionsSelectedStyle).addClass('disabled');
       this.highlightBasedOnSelectedIndex($(elem).next(),0);
       this.selectOption($(elem).next());
	   $(elem).next().find('.'+ options.optionsSelectedStyle).unbind('click');
         $(elem).next().find('.'+ options.optionsSelectedStyle).unbind('keypress');
	};

	this.bindHandlers = function(elem)
	{
	     var options = this.settings;
	   $(elem).next().find('li').bind("click",this,function(event){	
		  $(this).addClass('highlight');
		  event.data.hideOptions($(this).parent().parent());
		  event.data.selectOption($(this).parent().parent());
	  });

	   $(elem).next().find('li').bind("mousedown",this,function(event){	
		  event.data.optionClicked = true;
	  });

       $(elem).next().find('ul').bind("mouseleave",this,function(event){	
	 	  		  event.data.scrollClicked = false;
	   });
	  $(elem).next().find('ul').bind("mousedown",this,function(event){	
		  event.data.scrollClicked = true;
	  });

	  $(elem).next().find('ul').bind("focusout",this,function(event){	
			  event.data.scrollClicked = false;
	  });

	 $(elem).bind('disabled',this,function(event){
           event.data.disable(this);
    	  });
     
	  $(elem).bind('show',this,function(event){		
               $(this).next().show();
    	  });
		  
      $(elem).bind('hide',this,function(event){		  		 
               $(this).next().hide();
    	  });

       $(elem).bind('selectIndex',this,function(event,index){		
              event.data.highlightBasedOnSelectedIndex($(this).next(),index);
              event.data.selectOption($(this).next());
    	  });
      $(elem).next().find('.'+ options.optionsSelectedStyle).bind('click',this,function(event){
           event.data.toggleOptions($(this).parent());
	  });     

      var blurEvent = ($.browser.msie ? 'focusout' :'blur');
      $(elem).next().children('.'+ options.optionsSelectedStyle).bind(blurEvent,this,function(event){		
	           if(event.data.optionClicked) return (event.data.optionClicked=false);
			    if(event.data.scrollClicked){
				   $(this).focus();
				   return (event.data.scrollClicked=false);
				   }
		      	  event.data.hideOptions($(this).parent());
	  });

     $(elem).next().find('li').hover(function(){
	     $(this).siblings('.highlight').removeClass('highlight');
 	   	 $(this).addClass('highlight');
	  });     
	};
    this.highlightOption = function(containerList,newOption)
	{
         var newHighlight = $(containerList).children('ul').children('li').filter(newOption).filter(':first').addClass('highlight');
	     newHighlight.siblings().filter('.highlight').removeClass('highlight');	 
	};
    this.highlightBasedOnInputCharacter=function(containerList,charEntered)
	{
		if(charEntered>=97&&charEntered<=122)
		charEntered=charEntered-32;
		this.highlightOption(containerList,function(){return $(this).text().toUpperCase().charCodeAt(0) == charEntered && !$(this).hasClass('indicative');});
	};

	this.highlightBasedOnSelectedIndex=function(containerList,index)
	{
    	 this.highlightOption(containerList,':eq('+index+')');
	};

    this.selectOption = function(containerList)
	{  
	           var options = this.settings;
	           var highlight=$(containerList).children('ul').children('.highlight');
			   var selectedOption = $(containerList).children('.'+ options.optionsSelectedStyle).find('span');
      		  // if(highlight.attr('rel') == selectedOption.attr('rel')) return;         
		        selectedOption.text(highlight.text());
                selectedOption.attr('rel',highlight.attr('rel'));
         		selectedOption.attr('class',highlight.attr('class'));
				selectedOption.removeClass('highlight'); //removing highlight
				selectedOption.attr('style',highlight.attr('style'));
  		        $(containerList).prev('select').val(highlight.attr('rel'));
			    $(containerList).prev('select').change();
                $(containerList).css('zIndex',1);
				$(containerList).children('.'+ options.optionsSelectedStyle).focus();
	};
	this.toggleOptions = function(containerList)
	{ 
	  $(containerList).find('ul').toggle();
	   if($(containerList).children('ul').is(':visible'))
	     {   
			 $(containerList).css('zIndex',999); 
		 }else{
		 	 $(containerList).css('zIndex',1); 
		 }
	 
	};
	this.hideOptions = function(container)
	{
	  $(container).css('zIndex',1);
	  $(container).children('ul').css('display','none');	
	};
	this.keyHandlers = function(elem)
	{
	  var options = this.settings;
	  var expandableSelect =$(elem).next();
	   
	 var keyEventToListen='keypress '+ ($.browser.msie? 'keydown':'');
	 
	  expandableSelect.children('.'+ options.optionsSelectedStyle).bind(keyEventToListen,this,function(keyEvent)
	  {
      
       var _iExpandableSelect= keyEvent.data;
	   var keyPreventDefault=true;
	   var container = $(this).parent();
	   switch (keyEvent.keyCode)
						{					    
							case 27:
							     // ESC
							       _iExpandableSelect.hideOptions(container);			    
                                    return;
						     break;
							case 9:							         
							      //Tab
							      $(this).blur();
								  $(window)[0].focus();
								  keyPreventDefault=false;
   					       	break;
							case 13:
							 	 // Enter
								 keyPreventDefault=false;
                               	_iExpandableSelect.highlightOption(container,function(){ return $(this).attr('rel') == $(this).parent().siblings('.'+ options.optionsSelectedStyle).attr('rel') ; });
									 if(container.children('ul').is(':visible'))
										{ 
										  keyEvent.stopPropagation(); 
										  keyPreventDefault=true;
										  keyEvent.cancelBubble = true;
                                        } 							
																		
		                     _iExpandableSelect.hideOptions(container);
                            break;  
							case 33:
								//Page Up
							case 36:
								//Home
							    _iExpandableSelect.highlightOption(container,':first');
								break;
							case 34:
								//Page Down
							case 35:
								//End
								_iExpandableSelect.highlightOption(container,':last');
								break;				
							case 38:
								//Up
							case 37:
								//Left
								_iExpandableSelect.highlightOption(container,function(){ return $(this).next().hasClass('highlight'); });
								break;								
     						case 40:
								//Down
                            case 39:
								//Right
								_iExpandableSelect.highlightOption(container,function(){ return $(this).prev().hasClass('highlight'); });
								break;	
							default:
							   var charEntered=(!keyEvent.charCode)? keyEvent.keyCode : keyEvent.charCode;
							   _iExpandableSelect.highlightBasedOnInputCharacter(container,charEntered);								
						}
			if(keyPreventDefault==true)keyEvent.preventDefault();
			var highlightOffsetTop =container.find('ul').find('.highlight').position().top;
  		 	container.find('ul').scrollTop(highlightOffsetTop);

    		if(container.children('ul').is(':hidden'))
			{ 		   
			    _iExpandableSelect.selectOption($(this).parent());
			}
	  });
	};
	this.init(elem);
}
$.fn.expandableSelect = function(options){

var defaults = {
selectStyle:'selectStyle',
optionsStyle:'listStyle',
optionsSelectedStyle:'selected_option',
containerClass:'select_alt',
indicative :'indicative'
}

options = jQuery.extend(defaults, options);
return this.each(function() {
        var expandselect = new iExpandableSelect(options,this);
    });
}

})(jQuery);
